package milkyway.hightech.logging;

import java.io.IOException;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import java.util.logging.Logger;

import milkyway.hightech.banking.BankImpl;
import milkyway.hightech.customer.BankCustomerView;

/**
 *
 * @author michael
 */
public class ProxyLogging implements InvocationHandler
{
    private static final Logger logger =
        Logger.getLogger(ProxyLogging.class.getName());
    
    private BankImpl bank;

    /**
     *
     * @param object the object which will be used by the proxy.
     * @throws IOException any exception
     */
    public ProxyLogging(BankImpl bank) throws IOException
    {
        this.bank = bank;
    }

    /**
     *
     * @param obj
     * @return
     * @throws IOException
     */
    public static BankCustomerView newInstance(BankImpl obj) throws IOException
    {
        ClassLoader loader = obj.getClass().getClassLoader();
        Class<?>[] clazz = obj.getClass().getInterfaces();
        ProxyLogging logging = new ProxyLogging(obj);
        
        BankCustomerView bank =
            (BankCustomerView)Proxy.newProxyInstance(loader, clazz, logging);
        
        return bank;
    }

    /**
     *
     * @param proxy
     * @param m
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
    {
        Object result = null;

        try
        {
            String method = "Method: " + m.getName() + "\n";

            logger.fine(method);

            String arg = "";

            for (int i = 0; i < args.length; i++)
            {
                arg += " " + args[i].getClass().getSimpleName()
                       + " " + args[i].toString() + ", ";
            }

            arg += "\n";
            logger.fine(arg);
            result = m.invoke(bank, args);

            String res = "";

            if (result != null)
            {
                res += "- Result: " + result.getClass().getSimpleName()
                       + " " + result + "\n\n";
            }
            
            else
            {
                res += "null\n\n";
            }

            logger.fine(res);
        }
        
        catch (InvocationTargetException e)
        {
            logger.fine(e.getCause().getMessage());
        }
        
        catch (Exception e)
        {
            logger.fine(e.getMessage());
        }

        return result;
    }
}